package ar.com.raulsanchez.syncrolist;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.database.Cursor;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.SimpleCursorAdapter;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.support.v4.app.NavUtils;

public class ActivityListActivities extends ListActivity {
    private static final int ACTIVITY_CREATE = 0;
    private static final int ACTIVITY_EDIT	 = 1;
	
	private WebServiceInterface ws;
    private BDActividades mDbHelper;
    
	private int mUsuario_id;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_list_activities);
		
		mUsuario_id = getIntent().getExtras().getInt(BDActividades.ACTIVIDAD_USUARIO_ID);
		mDbHelper = new BDActividades(this);
        mDbHelper.open();
        
        registerForContextMenu(getListView());
        
        new ActivitiesSync().execute(mUsuario_id);        
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_list_activities, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			// This ID represents the Home or Up button. In the case of this
			// activity, the Up button is shown. Use NavUtils to allow users
			// to navigate up one level in the application structure. For
			// more details, see the Navigation pattern on Android Design:
			//
			// http://developer.android.com/design/patterns/navigation.html#up-vs-back
			//
			NavUtils.navigateUpFromSameTask(this);
			return true;
		case R.id.menu_add:
	        Intent i = new Intent(this, ActivityEditActivity.class);
	        i.putExtra(BDActividades.ACTIVIDAD_USUARIO_ID, mUsuario_id);
	        startActivityForResult(i, ACTIVITY_CREATE);
	        return true;
        case R.id.menu_sync:
        	new ActivitiesSync().execute(mUsuario_id);
        	return true; 	
		}
		return super.onOptionsItemSelected(item);
	}
	
	@Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.list_row, menu);
    }
	
    @Override
    public boolean onContextItemSelected(MenuItem item) {
    	AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();

        switch(item.getItemId()) {
            case R.id.menu_del:
            	new DeleteActivity().execute(info.id);
                return true;
            case R.id.menu_upd:
    	        Intent i = new Intent(this, ActivityEditActivity.class);
    	        i.putExtra(BDActividades.ID, info.id);
    	        startActivityForResult(i, ACTIVITY_EDIT);
                return true;
        }
        return super.onContextItemSelected(item);
    }
    
	private void uploadActivities() {
    	Cursor activitiesCursor = mDbHelper.getActivity(mUsuario_id,0);
    	startManagingCursor(activitiesCursor);
    	
    	if (activitiesCursor.getCount() > 0) {
    		ws = new WebServiceInterface();
    		for (int i = 0; i < activitiesCursor.getCount(); i++) {
				activitiesCursor.moveToPosition(i);
				int id		    = activitiesCursor.getInt(activitiesCursor.getColumnIndex(BDActividades.ID));
				String titulo   = activitiesCursor.getString(activitiesCursor.getColumnIndex(BDActividades.ACTIVIDAD_TITULO));
				String detalle  = activitiesCursor.getString(activitiesCursor.getColumnIndex(BDActividades.ACTIVIDAD_DETALLE));
				String fecha	= activitiesCursor.getString(activitiesCursor.getColumnIndex(BDActividades.ACTIVIDAD_FECHA));
				int version  	= activitiesCursor.getInt(activitiesCursor.getColumnIndex(BDActividades.ACTIVIDAD_VERSION));
				
				int actividad_id = ws.addActivity(mUsuario_id, titulo, detalle, fecha, version);
				if (actividad_id != 0)
		        	mDbHelper.setActivityId(id, actividad_id);
			}
    	}
    } // uploadActivities
	
	private void downloadActivities(JSONArray actividadesJsonArray) throws JSONException{
    	for (int i = 0; i < actividadesJsonArray.length(); i++) {
			int actividad_id = actividadesJsonArray.getJSONObject(i).getInt(BDActividades.ACTIVIDAD_ID);
			
			// If not  yet downloaded...
			if (mDbHelper.getActivityPerId(actividad_id).getCount() == 0) {
				String titulo  = actividadesJsonArray.getJSONObject(i).getString(BDActividades.ACTIVIDAD_TITULO);
				String detalle = actividadesJsonArray.getJSONObject(i).getString(BDActividades.ACTIVIDAD_DETALLE);
				String fecha   = actividadesJsonArray.getJSONObject(i).getString(BDActividades.ACTIVIDAD_FECHA);
				int version    = actividadesJsonArray.getJSONObject(i).getInt(BDActividades.ACTIVIDAD_VERSION);
				
				mDbHelper.addActivity(actividad_id, titulo, detalle, fecha, mUsuario_id, version);
			}
		}
    } // downloadActivities
	
	private void syncUpdatedActivities(JSONArray actividadesJsonArray) throws JSONException{
    	for (int i = 0; i < actividadesJsonArray.length(); i++) {
    		
			int actividad_id = actividadesJsonArray.getJSONObject(i).getInt(BDActividades.ACTIVIDAD_ID);
			String titulo    = actividadesJsonArray.getJSONObject(i).getString(BDActividades.ACTIVIDAD_TITULO);
			String detalle	 = actividadesJsonArray.getJSONObject(i).getString(BDActividades.ACTIVIDAD_DETALLE);
			String fecha     = actividadesJsonArray.getJSONObject(i).getString(BDActividades.ACTIVIDAD_FECHA);
			int version   	 = actividadesJsonArray.getJSONObject(i).getInt(BDActividades.ACTIVIDAD_VERSION);
			
			Cursor activityCursor = mDbHelper.getActivityPerId(actividad_id);
			startManagingCursor(activityCursor);
			activityCursor.moveToFirst();
			
			if (activityCursor.getCount() == 1) {
				
				int version_local = activityCursor.getInt(activityCursor.getColumnIndex(BDActividades.ACTIVIDAD_VERSION));
				
				if (version_local != version) {
				
					// if remote is newer...
					if (Long.valueOf(version_local) < Long.valueOf(version))
						mDbHelper.updActivity(actividad_id, titulo, detalle, fecha, version);
					else { // if local is newer...
						String local_titulo 	 = activityCursor.getString(activityCursor.getColumnIndex(BDActividades.ACTIVIDAD_TITULO));
						String local_detalle   = activityCursor.getString(activityCursor.getColumnIndex(BDActividades.ACTIVIDAD_DETALLE));
						String local_fecha		 = activityCursor.getString(activityCursor.getColumnIndex(BDActividades.ACTIVIDAD_FECHA));
						
						WebServiceInterface ws = new WebServiceInterface();
						ws.updActivity(actividad_id, local_titulo, local_detalle, local_fecha, version_local);
					}
				}
			}
		}
    } // syncUpdatedActivities
	
	private void syncDeletedActivities(JSONArray actividadesJsonArray) throws JSONException {
    	Cursor activitiesCursor = mDbHelper.getActivities(mUsuario_id);
    	startManagingCursor(activitiesCursor);
    	
    	if (activitiesCursor.getCount() > 0) {
    		boolean encontrado;
    		int j;
    		ArrayList<Integer> activitiesToDelete = new ArrayList<Integer>();
    		
    		for (int i = 0; i < activitiesCursor.getCount(); i++) {
    			activitiesCursor.moveToPosition(i);
				encontrado = false;
				j = 0;
				
				int id			 = activitiesCursor.getInt(activitiesCursor.getColumnIndex(BDActividades.ID));
				int actividad_id = activitiesCursor.getInt(activitiesCursor.getColumnIndex(BDActividades.ACTIVIDAD_ID));
				
				while ((j < actividadesJsonArray.length()) && !(encontrado)) {
					if (actividadesJsonArray.getJSONObject(j).getInt(BDActividades.ACTIVIDAD_ID) == actividad_id)
						encontrado = true;
					j++;
				}
				
				if ( ! encontrado)
					activitiesToDelete.add(id);
			}
    		
    		for(int i = 0; i < activitiesToDelete.size(); i++) {
    			mDbHelper.delActivity(activitiesToDelete.get(i),false);
    		}
    	}
    } // syncDeletedActivities
	
    private void loadList() {
    	Cursor activitiesCursor = mDbHelper.getActivities(mUsuario_id);
        startManagingCursor(activitiesCursor);

        String[] desde = new String[]{BDActividades.ACTIVIDAD_TITULO};
        int[]    hasta = new int[]{R.id.textRow};

        SimpleCursorAdapter actividades = new SimpleCursorAdapter(this, R.layout.list_row, activitiesCursor, desde, hasta);
        setListAdapter(actividades);
    } // loadList
	
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	  if (requestCode == ACTIVITY_CREATE) {

    	     if(resultCode == RESULT_OK){      
    	         new AddActivities().execute();        
    	     }
    	     
    	     if (resultCode == RESULT_CANCELED) {    
    	     }
    	  }
    	  else if (requestCode == ACTIVITY_EDIT) {

     	     if(resultCode == RESULT_OK){      
     	    	new ActivitiesSync().execute(mUsuario_id);    
     	     }     
     	     if (resultCode == RESULT_CANCELED) {    
     	     }
     	  }
    } // onActivityResult
    
    
    
    //------------------------------------
  	// SUBCLASE ACTIVITIES SYNC
  	//------------------------------------
  	private class ActivitiesSync extends AsyncTask<Integer, Void, String> {

  		private final ProgressDialog dialog = new ProgressDialog(
                  ActivityListActivities.this);

	      protected void onPreExecute() {
	      	  this.dialog.setTitle("Sincronizando actividades");
	    	  this.dialog.setMessage("Por favor espere...");
	    	  this.dialog.show();
	      }
	
	      protected String doInBackground(Integer... data) {
	  		ws = new WebServiceInterface();
	      	String result = ws.listActivities(data[0]); //json

	      	uploadActivities();
			
			if (result.length() > 0) {
				try {
					JSONArray actividadesJsonArray = new JSONArray(result);
					downloadActivities(actividadesJsonArray);
					syncUpdatedActivities(actividadesJsonArray);
					syncDeletedActivities(actividadesJsonArray);
				} catch (JSONException e) {
					System.out.println(e.getMessage());
				}
			} // if
	      	
	      	return result;
	      }
	
	      protected void onPostExecute(String arg) {
	      	if (this.dialog.isShowing()) {
	      		this.dialog.dismiss();
	      	}
      		loadList();
	      }

  	} // subclass ActivitiesSync

  	
    //------------------------------------
  	// SUBCLASE DELETE ACTIVITY
  	//------------------------------------
  	private class DeleteActivity extends AsyncTask<Long, Void, Integer> {

  		private final ProgressDialog dialog = new ProgressDialog(
                  ActivityListActivities.this);

	      protected void onPreExecute() {
	      	  this.dialog.setTitle("Eliminando actividad");
	    	  this.dialog.setMessage("Por favor espere...");
	    	  this.dialog.show();
	      }
	
	      protected Integer doInBackground(Long... data) {
	    	Cursor activitiesCursor = mDbHelper.getActivity(data[0]);
	      	startManagingCursor(activitiesCursor);
	      	int actividad_id = activitiesCursor.getInt(activitiesCursor.getColumnIndex(BDActividades.ACTIVIDAD_ID));
	    	
	      	int result = 0;
	      	
	    	if (mDbHelper.delActivity(data[0],false)) {
	    		ws = new WebServiceInterface();
		      	result = ws.delActivity(actividad_id); //actividad_id
	    	}
	      	
	      	return result;
	      }
	
	      protected void onPostExecute(Integer arg) {
	      	if (this.dialog.isShowing()) {
	      		this.dialog.dismiss();
	      	}
      		loadList();
	      }

  	} // subclass DeleteActivity
  	
  	
  	//------------------------------------
  	// SUBCLASE ADD ACTIVITIES
  	//------------------------------------
  	private class AddActivities extends AsyncTask<Void, Void, Void> {

		private final ProgressDialog dialog = new ProgressDialog(
	              ActivityListActivities.this);
	
	      protected void onPreExecute() {
	      	  this.dialog.setTitle("Agregando actividad");
	    	  this.dialog.setMessage("Por favor espere...");
	    	  this.dialog.show();
	      }
	
	      protected Void doInBackground(Void... data) {
	    	uploadActivities();
	    	return null;
	      }
	
	      protected void onPostExecute(Void arg) {
	      	if (this.dialog.isShowing()) {
	      		this.dialog.dismiss();
	      	}
	  		loadList();
	      }

  	} // subclass AddActivities
  	
}
